from flask import request
from flask_socketio import SocketIO, emit, join_room, leave_room
from utils.randomUtils import generate_random_token, generate_random_by_time
import threading
from .baseGraphNode import BaseGraphNode
from .sessionInfo import SessionInfo

class HttpGraphNode(BaseGraphNode):
    
    def get_socketio_instance(self):
        if self._socketio_instance is None:
            from managers.userManager import ProjectManager
            self._socketio_instance = SocketIO(ProjectManager.app, cors_allowed_origins="*")
        return self._socketio_instance
    
    def __init__(self, id:str, data:dict, graphNodeManager, random_key:str):
        super().__init__(id, data, graphNodeManager, random_key)
        self.route = data['data']['route']
        self.enWS = data['data']['enWS']
        self.enInterrupt = data['data']['enInterrupt']
        self.full_url = '/socket.io/' + generate_random_token(random_key)
        self._ws_token = self.full_url
        self.running = False
        from managers.userManager import ProjectManager
        self._ws_token = None  
        self._socketio_instance = SocketIO(ProjectManager.app, cors_allowed_origins="*")
        self.graphNodeManager.http_node = self

    def execute(self, session_info: SessionInfo=None):
        if not self.running:
            if self.route in self.graphNodeManager.project.onlineRoutes:
                self.graphNodeManager.project.onlineRoutes.pop(self.route)
            self.running = True
            
            # 获取全局 SocketIO 实例
            socketio_instance = self.get_socketio_instance()
            
            def create_websocket_route(route, full_url):
                @socketio_instance.on('connect', namespace=full_url)
                def on_connect():
                    print(f"WebSocket connected on route: {full_url} User sid:{request.sid}")
                    emit('response', {'data': 'Connected to WebSocket!'})

                @socketio_instance.on(route, namespace=full_url)
                def handle_message(msg):
                    sid = request.sid
                    print(f'Received message: {msg}, sid:{sid}')
                    sessionInfo = self.graphNodeManager.sid_to_sessionInfo.get(sid, None) 
                    if sessionInfo is None: 
                        sessionInfo = self.graphNodeManager.createSessionInfo(
                            generate_random_by_time(),
                            socketio_instance, 
                            sid, 
                            route,
                            full_url
                        )
                        join_room(sid)  
                    if sessionInfo.id not in self.dict['out']: 
                        self.dict['out'][sessionInfo.id] = {}
                    if 'query-msg' not in self.dict['out'][sessionInfo.id]: 
                        self.dict['out'][sessionInfo.id]['query-msg'] = []
                    self.dict['out'][sessionInfo.id]['query-msg'].append(msg)
                    self.executed_num += 1
                    self.flow_next(sessionInfo)
                    
                @socketio_instance.on('disconnect', namespace=full_url)
                def on_disconnect():
                    sid = request.sid
                    print(f"WebSocket disconnected on route: {full_url} User sid: {sid}")
                    leave_room(sid)
            
            # 启动 WebSocket 服务器（如果还没有启动）
            if not self.graphNodeManager.project.is_websocket_running:
                threading.Thread(target=create_websocket_route, args=(self.route, self.full_url)).start()
                self.graphNodeManager.project.addOnlineRoute(self.route, 'message', self.name)
                self.graphNodeManager.project.is_websocket_running = True
                print(f'WebSocket server started and listening on route: {self.full_url}')
        else:
            # 返回消息的逻辑
            assert session_info is not None, "session_info should not be None when returning message"
            returnMsg = ''
            if 'return-msg' in self.dict['in']:
                msgFrom = self.dict['in']['return-msg']
                prenode = self.graphNodeManager.nodesByIdDict[msgFrom['nodeId']]
                returnMsg = prenode.dict['out'][session_info.id][msgFrom['handle']][-1]
            print(f'returnMsg: {returnMsg}')
            session_info.ws.emit('response', {'data': returnMsg}, room=session_info.sid, namespace=self.full_url)
        return self.full_url
    
    def stop(self):
        if not self.running:
            return
            
        self.running = False
        self.graphNodeManager.project.removeOnlineRoute(self.route)
        
        # 如果没有其他路由在使用 WebSocket 服务器，则关闭它
        if not self.graphNodeManager.project.onlineRoutes:
            if self._socketio_instance is not None:
                self._socketio_instance.close()
                self._socketio_instance = None
                self.graphNodeManager.project.is_websocket_running = False    
        if self._socketio_instance is not None:
            self._socketio_instance.close()
